package pri.hillchen.std.concurren.chapter7;

import java.util.Random;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.CountDownLatch;

/**
 * @author:hillchen
 * @DESCRIPTION:
 * @Date: Created in 11:20 2018/2/9 0009.
 */
public class BlockingInterruptedDemo {
    static class ErrorInterruptedException extends RuntimeException{
        public ErrorInterruptedException() {
        }

        public ErrorInterruptedException(String message) {
            super(message);
        }

        public ErrorInterruptedException(String message, Throwable cause) {
            super(message, cause);
        }

        public ErrorInterruptedException(Throwable cause) {
            super(cause);
        }

        public ErrorInterruptedException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
            super(message, cause, enableSuppression, writableStackTrace);
        }
    }
    interface CancelableRunner extends Runnable{
        void cancel();
    }

    static abstract class AbstractCancelableRunner implements CancelableRunner{
        abstract void beforeCancel();
        public void cancel() {
            beforeCancel();
            Thread.currentThread().interrupt();
        }
    }

    public static void main(String[] args) throws InterruptedException {
        final Random random = new Random();
        final BlockingQueue<Integer> blockingQueue = new ArrayBlockingQueue<Integer>(15);
        final CountDownLatch starLatch = new CountDownLatch(1);
        CancelableRunner  prouctorRunner = new AbstractCancelableRunner(){
            private boolean isRun = true;
            public void run() {
                try {
                    starLatch.await();
                    while (isRun){
                        blockingQueue.put(random.nextInt());
                        Thread.sleep(10);
                    }
                } catch (InterruptedException e) {
                    /**
                     * 判断是否为通过取消方法中断等待,如果不是，则抛出未受检查异常
                     */
                    if(isRun){
                        System.out.println();
                    }else{
                        throw new ErrorInterruptedException(e);
                    }

                }
            }

            void beforeCancel() {
                isRun = false;
            }
        };

        CancelableRunner  comsumerRunner = new AbstractCancelableRunner(){
            private boolean isRun = true;
            public void run() {
                try {
                    starLatch.await();
                    while (isRun){
                        Integer num = blockingQueue.take();
                        System.out.println(num);
                        Thread.sleep(11);
                    }
                } catch (InterruptedException e) {
                    /**
                     * 判断是否为通过取消方法中断等待,如果不是，则抛出未受检查异常
                     */
                    if(isRun){
                        System.out.println();
                    }else{
                        throw new ErrorInterruptedException(e);
                    }

                }
            }
            void beforeCancel() {
                isRun = false;
            }
        };
        new Thread(prouctorRunner).start();
        new Thread(comsumerRunner).start();
        starLatch.countDown();

        Thread.sleep(1000);
        prouctorRunner.cancel();
        comsumerRunner.cancel();

    }
}
